<?php
/**
 * Created by PhpStorm.
 * User: 84071
 * Date: 2018-08-11
 * Time: 10:55
 */
namespace weixinhack;

class WxBase{
    /**
     * @param $appid    微信APP_ID
     * @param $secret   微信APP_KEY
     * @return bool|mixed   返回ACCSEE_TOKEN
     */
    public function access_token($appid,$secret){
        if(webCacheHas('wx_accsee_token')){
            $access = webCacheGet('wx_accsee_token');
        }else{
            $access_token = $this->request_post("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}");
            $access = json_decode($access_token,true);
            webCacheSet('wx_accsee_token',$access['access_token'],$access['expires_in']);
        }
        return $access;
    }

    /**
     * @param $token 微信TOKEN
     * @return bool|mixed|string 返回菜单列表
     */
    public function get_menus($token){
        $menus = $this->request_post("https://api.weixin.qq.com/cgi-bin/menu/get?access_token={$token}");
        $menus = json_decode($menus,true);
        return $menus;
    }

    /**
     * @param $appid    微信appid
     * @param $redirect_uri 返回地址
     * @return string   拼接url
     */
    public function get_code($appid,$redirect_uri){
        $redirect_uri = urlencode($redirect_uri);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$redirect_uri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
    }

    /**
     * @param $appid    微信appid
     * @param $secret   微信secret
     * @param $code 用户code
     * @return bool|mixed|string    返回openid和token token有效期为30天
     */
    public function get_user_token($appid,$secret,$code){
        $usertoken = $this->request_post("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code");
        $usertoken = json_decode($usertoken,true);
        return $usertoken;
    }
    //  获取详细信息
    public function get_user_data($access_token,$openid){
        $userdata = $this->request_post("https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN");
        $userdata = json_decode($userdata,true);
        return $userdata;
    }


    /**
     * @param $data 菜单数据
     * @param $token  微信token
     * @return mixed|string 返回菜单列表
     */
    public function post_menu($data,$token){
        $menu = $this->request_json("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={$token}",$data);
        $menu = json_decode($menu,true);
        return $menu;
    }

    /**
     * @param $token    微信token
     * @return bool|string 返回素材总数
     */
    public function get_mediacont($token){
        $media = $this->request_post("https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token={$token}");
        return $media;
    }
    //  长链接转短链接
    public function get_shorturl($token,$long_url){
        $data = array(
            'action' => 'long2short',
            'long_url' => $long_url,
        );
        $data = json_encode($data,LIBXML_NOCDATA);
        $media = $this->request_json("https://api.weixin.qq.com/cgi-bin/shorturl?access_token={$token}",$data);
        return $media;
    }


    /**
     * @param $data 获取的内容
     * @param $token 微信token
     * @return string
     */
    public function get_media($data,$token){
        $media = $this->request_json("https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token={$token}",$data);
        return $media;
    }

    /**
     * @param string $url   访问的链接
     * @param array $post_data  附加参数
     * @return bool|string  返回值
     */
    public function request_post($url = '', $post_data = array()){
        $postdata = http_build_query($post_data);
        $options = array(
            'https' => array(
                'method' => 'POST',
                'header' => 'Content-type:application/x-www-form-urlencoded',
                'content' => $postdata,
                'timeout' => 15 * 60 // 超时时间（单位:s）
            )
        );
        $context = stream_context_create($options);
        $result = file_get_contents($url, false, $context);
        return $result;
    }

    //  获取jsapi
    public function get_jsapi($access_token){
        if(webCacheHas('wxjsapi')){
            $jsapi = webCacheGet('wxjsapi');
        }else{
            $jsapi = $this->request_post("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$access_token}&type=jsapi");
            $jsapi = json_decode($jsapi,true);
            if($jsapi['errcode'] == '0'){
                $jsapi = webCacheSet('wxjsapi',$jsapi['ticket'],$jsapi['expires_in']);
            }else{
                return false;
            }
        }
        return $jsapi;
    }
    //  获取js签名
    public function get_jssing($ticket,$urls){
        $jssing = array(
            'noncestr' => $this->getNonceStr(),
            'jsapi_ticket' => $ticket,
            'timestamp' => time(),
            'url' => $urls,
        );
        ksort($jssing);
        foreach ($jssing as $k => $v){
            $newdata[] = "{$k}={$v}";
        }
        $string = implode('&',$newdata);
        $jssing['sing'] = sha1($string);
        return $jssing;
    }

    /**
     * @param $webdatas 微信配置
     * @param $order    订单信息
     * @return array|bool|mixed|string  返回统一下单信息
     */
    public function pay_add($webdatas,$order){
        $payadd = array(
            'appid' => $webdatas['wxappid'],
            'mch_id' => $webdatas['wxmchid'],
            'nonce_str' => $this->getNonceStr(),
            'body' => $order['title'], //商品标题
            'openid' => $order['conf']['usertoken'], //商品标题
            'out_trade_no' => $order['loid'], //订单号
            'total_fee' => $order['pricemoney'], //标价金额
            'spbill_create_ip' => request()->ip(), //IP
            'notify_url' => url('Index/wxtoken'), //返回地址
            'trade_type' => 'JSAPI', //交易类型公众号
        );

//            'total_fee' => $order['pricemoney'], //标价金额
        ksort($payadd);
        $payadd['sign'] = $this->res_sign($payadd,$webdatas['wxmckey']); //签名
        $payadd = $this->res_xml($payadd);
        $payadd = $this->request_json("https://api.mch.weixin.qq.com/pay/unifiedorder",$payadd);
        $payadd = $this->res_data($payadd);
        return $payadd;
    }
    //  查询订单
    public function get_payend($webdatas,$out_trade_no){
        $payend = array(
            'appid' => $webdatas['wxappid'],
            'mch_id' => $webdatas['wxmchid'],
            'out_trade_no' => $out_trade_no,
            'nonce_str' => $this->getNonceStr(),
            'sign_type' => "MD5",
        );
        ksort($payend);
        $payend['sign'] = $this->res_sign($payend,$webdatas['wxmckey']); //签名
        $payend = $this->res_xml($payend);
        $payend = $this->request_json("https://api.mch.weixin.qq.com/pay/orderquery",$payend);
        $payend = $this->res_data($payend);
        return $payend;
    }
    //  公众号支付
    public function get_play($webdatas,$playadd){
        $playdata = array(
            'appId' => $webdatas['wxappid'],
            'timeStamp' => time(),
            'nonceStr' => $this->getNonceStr(),
            'package' => "prepay_id={$playadd['prepay_id']}",
            'signType' => 'MD5',
        );
        ksort($playdata);
        $playdata['paySign'] = $this->res_sign($playdata,$webdatas['wxmckey']); //签名
        return $playdata;
    }
    //  微信退款
    public function get_tuikuan($webdata,$data){
        $tuikuan = array(
            'appid' => $webdata['wxappid'],
            'mch_id' => $webdata['wxmchid'],
            'nonce_str' => $this->getNonceStr(),
            'out_trade_no' => $data['orderplay']['lsoid'],    //  订单号
            'out_refund_no' => $data['oid'],  //  退款单号
            'total_fee' => $data['tpricemoney'],  //  订单金额
            'refund_fee' => $data['tpricemoney'],  //  退款金额
        );
        ksort($tuikuan);
        $tuikuan['sign'] = $this->res_sign($tuikuan,$webdata['wxmckey']); //签名
        $tuikuan = $this->res_xml($tuikuan);
        $tuikuan = $this->request_json("https://api.mch.weixin.qq.com/secapi/pay/refund",$tuikuan,true);
        $tuikuan = $this->res_data($tuikuan);
        return $tuikuan;
    }
    //  生成签名
    public function res_sign($data,$wxmckey = null){
        foreach ($data as $k => $v){
            $newdata[] = "{$k}={$v}";
        }
        if(empty($wxmckey)){
            $string = implode('&',$newdata);
        }else{
            $string = implode('&',$newdata)."&key=".$wxmckey;
        }
        $string = strtoupper(md5($string));
        return $string;
    }
    //  生成xml
    public function res_xml($data){
        $xml = "<xml>";
        foreach ($data as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }
    /**
     * 将xml转为array
     * @param string $xml
     * @throws WxPayException
     */
    public function res_data($xml){
        if(!$xml){
            return false;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }
    /**
     *
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public function getNonceStr($length = 32){
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }
    /**
     * @param $url  请求链接
     * @param $arr  需要转换成json的数组
     * @return string   返回值
     */
    public function request_json($url, $data = null,$pem = false) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        if($pem == true){
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, EXTEND_PATH.'weixinhack/cart/apiclient_cert.pem');
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, EXTEND_PATH.'weixinhack/cart/apiclient_key.pem');
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($data))
        );
        ob_start();
        curl_exec($ch);
        $return_content = ob_get_contents();
        ob_end_clean();
        return $return_content;
    }
}